/**
 * 公司的域名倒过来写.项目名.模块名.子包
 */
package com.niit.common.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * ~标准的JDBC ~单例模式:啥是单例模式;在一个JVM中,只有一个对象 让构造方法私有 提供一个属性;类型是自己,new一个对象
 * 提供一个方法返回值是自己,修饰符是public static
 * <p>
 * ~封装JDBC 将加载驱动只执行一次 第二步放到一个方法中 将经常修改的内容放到配置文件中;资源文件,ResourceBundle
 *
 * @author wangshMac
 */
public class DbUtil {
    /**
     * 为了属性的安全:设置值和获取值(set/get)
     */
    private static DbUtil INSTANCE = new DbUtil();

    /* 变量 */
    private String driver = ConstatFinalUtil.SYS_BUNDLE.getString("jdbc.driver");
    /*
     * jdbc的url; http://www.cnblogs.com/iamfy/archive/2012/07/11/2586869.html
     * 参数是:url; jdbc:mysql://localhost:3306/userscenter_20180108?user=&password=
     */
    private String url = ConstatFinalUtil.SYS_BUNDLE.getString("jdbc.url");
    private String user = ConstatFinalUtil.SYS_BUNDLE.getString("jdbc.user");
    private String password = ConstatFinalUtil.SYS_BUNDLE.getString("jdbc.password");

    /**
     * 私有的构造方法
     */
    private DbUtil() {
        /* 单例模式,此代码只执行一次 */
        try {
            /* 加载驱动 */
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            System.out.println("==加载驱动失败==");
            e.printStackTrace();
        }
    }

    /**
     * static:构造方法私有了,外面的类不能new了,如果此方法不被static修饰,那么getInstance,是必须得new吧;只能被static修饰
     *
     * @return
     */
    public static DbUtil getInstance() {
        return INSTANCE;
    }

    /**
     * 获取一个链接
     *
     * @return
     */
    public Connection getConnection() {
        /* 获取链接 */
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            System.out.println("==获取链接失败==");
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 关闭链接,关闭语句,关闭rs
     *
     * @param connection jdbc的链接
     * @param st         sql语句对象
     * @param rs         查询的结果集
     */
    public void closeAll(Connection connection, Statement st, ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
                rs = null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        try {
            if (st != null) {
                st.close();
                st = null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        try {
            if (connection != null) {
                connection.close();
                connection = null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // stardandJDBC();
        encapsulationJDBC();

        /* 测试单例模式 */
        for (int i = 0; i < 10; i++) {
            /* 不能new对象,要使用getInstance方法 */
            System.out.println(DbUtil.getInstance());
        }
    }

    /**
     * 封装后的JDBC
     */
    public static void encapsulationJDBC() {
        System.out.println("==封装后的JDBC==");
        String sql = "select * from a_role ; ";

        PreparedStatement ps = null;
        ResultSet rs = null;

        /* 先创建对象,不能new */
        DbUtil dbUtil = DbUtil.getInstance();
        /* 获取链接 */
        Connection connection = dbUtil.getConnection();
        try {
            ps = connection.prepareStatement(sql);
            rs = ps.executeQuery();
            /*
             * 到底是循环还是选择 如果查询的结果是多条,就用判断 如果是单条:就用选择
             *
             * rs == 班长== 迭代器==enumeration(枚举)
             */
            while (rs.next()) {
                /*
                 * 参数为整数:指的是sql语句执行以后;列的顺序 参数为字符串时:指的是sql语句执行以后列的别名;
                 */
                int id = rs.getInt(1);
                String name = rs.getString("name");
                System.out.println("id:" + id + ";name" + name);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            dbUtil.closeAll(connection, ps, rs);
        }
    }

    /**
     * 标准的JDBC代码 查询角色表中所有记录
     */
    private static void stardandJDBC() {
        /*
         * Jdbc:四步走: 加载驱动 获取链接 操作数据库 关闭链接
         *
         * 查询角色表中所有的记录
         */
        String driver = "com.mysql.jdbc.Driver";
        /*
         * jdbc的url; http://www.cnblogs.com/iamfy/archive/2012/07/11/2586869.html
         * 参数是:url; jdbc:mysql://localhost:3306/userscenter_20180108?user=&password=
         */
        String url = "jdbc:mysql://localhost:3306/userscenter_20180108?useSSL=true";
        String user = "root";
        String password = "123456";
        /* 写上sql语句 */
        String sql = "select * from a_role ; ";

        /* 为对象赋初始值 */
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            /* 加载驱动 */
            Class.forName(driver);
            /* 获取链接 */
            connection = DriverManager.getConnection(url, user, password);
            /*
             * 操作数据库 创建一个SQL语句,将SQL语句发送到数据库中 Statement:木有预先加载; String name = "aa" ; String
             * pass = "' or 1 = 1 or name = '232323232323" ;//SQL注入 select * from users
             * where name = '"+ name +"' and password = '" + name + "' ;
             * preparedStatement:预先加载 ?:占位符 SQL注入
             */
            ps = connection.prepareStatement(sql);
            rs = ps.executeQuery();
            /*
             * 到底是循环还是选择 如果查询的结果是多条,就用判断 如果是单条:就用选择
             *
             * rs == 班长== 迭代器==enumeration(枚举)
             */
            while (rs.next()) {
                /*
                 * 参数为整数:指的是sql语句执行以后;列的顺序 参数为字符串时:指的是sql语句执行以后列的别名;
                 */
                int id = rs.getInt(1);
                String name = rs.getString("name");
                System.out.println("id:" + id + ";name" + name);
            }
        } catch (ClassNotFoundException e) {
            System.out.println("==加载驱动失败==");
            e.printStackTrace();
        } catch (SQLException e) {
            System.out.println("==获取链接失败==");
            e.printStackTrace();
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                    rs = null;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

            try {
                if (ps != null) {
                    ps.close();
                    ps = null;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

            try {
                if (connection != null) {
                    connection.close();
                    connection = null;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
